package com.ydl.shopping.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ydl.shopping.core.enums.ResultEnum;
import com.ydl.shopping.domain.TbRole;
import com.ydl.shopping.domain.TbUser;
import com.ydl.shopping.domain.TbUserRole;
import com.ydl.shopping.exception.ServiceException;
import com.ydl.shopping.mapper.TbUserRoleMapper;
import com.ydl.shopping.service.ITbRoleService;
import com.ydl.shopping.service.ITbUserRoleService;
import com.ydl.shopping.service.ITbUserService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class TbUserRoleServiceImpl extends ServiceImpl<TbUserRoleMapper, TbUserRole> implements ITbUserRoleService {
    private final ITbUserService tbUserService;

    @Resource
    private ITbRoleService tbRoleService;

    public TbUserRoleServiceImpl(@Lazy ITbUserService tbUserService) {
        this.tbUserService = tbUserService;
    }


    @Override
    public String saveUserRole(Long userId, List<Long> roleIDs) {
        TbUser tbUser = tbUserService.getById(userId);
        if (tbUser == null) {
            return "用户不存在";
        }
        // 判断是否空角色
        if (roleIDs.isEmpty()) {
            return null;
        }
        // 获取用户原有角色IDs
        List<Long> userRoleIds = getUserRoleIds(userId);

        // 先取出相同值 a与b的交集 获取要保留的 retainIds
        Collection<Long> retainIds = CollectionUtils.intersection(userRoleIds, roleIDs);
        // 再取出不同值 a与retainIds的差集 获取要删除的 deleteIds
        Collection<Long> deleteIds = CollectionUtils.subtract(userRoleIds, retainIds);
        for (Long deptId : deleteIds) {
            Long userRoleId = getUserRoleId(userId, deptId);
            if (userRoleId == null) {
                continue;
            }
            boolean delResult = removeById(userRoleId);
            if (!delResult) {
                throw new ServiceException(ResultEnum.ERROR);
            }
        }

        // 再取出不同值 b与retainIds的差集 获取要新增的 saveIds
        Collection<Long> saveIds = CollectionUtils.subtract(roleIDs, retainIds);

        for (Long roleId : saveIds) {
            TbRole tbRole = tbRoleService.getById(roleId);
            if (tbRole == null) {
                continue;
            }
            boolean saveResult = save(new TbUserRole(userId, roleId));
            if (!saveResult) {
                throw new ServiceException(ResultEnum.ERROR);
            }
        }

        return null;
    }

    /**
     * 获取用户角色ID
     *
     * @param userId 用户ID
     * @param roleId 部门ID
     * @return 用户角色ID
     */
    private Long getUserRoleId(Long userId, Long roleId) {
        TbUserRole tbUserRole = query().eq("user_id", userId).eq("role_id", roleId).one();
        if (tbUserRole == null) {
            return null;
        }
        return tbUserRole.getId();
    }

    @Override
    public String saveUserRoleByRoleId(Long roleId, List<Long> userIDs) {
        TbRole tbRole = tbRoleService.getById(roleId);
        if (tbRole == null) {
            return "角色不存在";
        }
        List<TbUserRole> tbUserRoles = query().eq("role_id", roleId).list();
        if (tbUserRoles != null && !tbUserRoles.isEmpty()) {
            List<Long> roleUserIds = tbUserRoles.stream().map(TbUserRole::getUserId).collect(Collectors.toList());

            // 求新增用户Id与原有角色用户ID差集，获取不重复的新用户Id
            Collection<Long> saveUserIds = CollectionUtils.subtract(userIDs, roleUserIds);

            for (Long userId : saveUserIds) {
                boolean saveResult = save(new TbUserRole(userId, roleId));
                if (!saveResult) {
                    throw new ServiceException(ResultEnum.ERROR);
                }
            }

            return null;
        }

        for (Long userId : userIDs) {
            boolean saveResult = save(new TbUserRole(userId, roleId));
            if (!saveResult) {
                throw new ServiceException(ResultEnum.ERROR);
            }
        }

        return null;
    }

    @Override
    public List<Long> getUserRoleIds(Long userId) {
        List<TbUserRole> userRoles = query().eq("user_id", userId).list();
        return userRoles.stream().map(TbUserRole::getRoleId).collect(Collectors.toList());
    }

    @Override
    public List<TbUserRole> getUserRoleListByRoleId(TbUser tbUser) {
        List<Long> roleIds = tbUser.getRoleIds();
        Long roleId = roleIds.get(0);
        QueryWrapper<TbUserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", roleId);

        List<TbUser> list = tbUserService.list(null);
        if (!list.isEmpty()) {
            List<Long> userIds = list.stream().map(TbUser::getId).collect(Collectors.toList());
            queryWrapper.in("user_id", userIds);
        } else {
            return Collections.emptyList();
        }

        List<TbUserRole> sysUserRoles = list(queryWrapper);
        for (TbUserRole tbUserRole : sysUserRoles) {
            Long userId = tbUserRole.getUserId();
            TbUser user = tbUserService.getById(userId);
            tbUserRole.setTbUser(user);
        }

        String username = tbUser.getUsername();
        if (StrUtil.isNotBlank(username)) {
            sysUserRoles = sysUserRoles.stream().filter(item -> item.getTbUser().getUsername().contains(username)).collect(Collectors.toList());
        }

        String tel = tbUser.getTel();
        if (StrUtil.isNotBlank(tel)) {
            sysUserRoles = sysUserRoles.stream().filter(item -> item.getTbUser().getTel().contains(tel)).collect(Collectors.toList());
        }

        Integer type = tbUser.getType();
        if (type != null) {
            sysUserRoles = sysUserRoles.stream().filter(item -> item.getTbUser().getType().equals(type)).collect(Collectors.toList());
        }

        Integer status = tbUser.getStatus();
        if (status != null) {
            sysUserRoles = sysUserRoles.stream().filter(item -> item.getTbUser().getStatus().equals(status)).collect(Collectors.toList());
        }

        return sysUserRoles;
    }

    @Override
    public List<TbUser> getUserRoleListNotByRoleId(TbUser tbUser) {
        List<Long> roleIds = tbUser.getRoleIds();
        Long roleId = roleIds.get(0);

        List<TbUserRole> sysUserRoles = query().eq("role_id", roleId).list();
        List<Long> userIds = sysUserRoles.stream().map(TbUserRole::getUserId).collect(Collectors.toList());

        List<TbUser> sysUsers = tbUserService.selectList(tbUser);
        Iterator<TbUser> iterator = sysUsers.iterator();

        while (iterator.hasNext()) {
            TbUser next = iterator.next();
            for (Long userId : userIds) {
                if (userId.equals(next.getId())) {
                    iterator.remove();
                }
            }
        }

        return sysUsers;
    }
}
